# -*- coding: UTF-8 -*-
import re
from django.conf import settings

"""
The part below comes from djangosnippets.org
snippet number 1324

This loads in css and javascript files where you want them (usually in the
head) - but allows you to put them anywhere in your code - i.e. in a
TemplateTag.

so your head code will look like this:

<head> ... <!-- HEAD_init --> ... </head>

then somewhere in your templates you can load in javascript or css files like
so:

<!-- HEAD_include myfile.js myotherfile.css -->

It automatically checks if you've already included the files, and only puts
them in once. It automatically figures out if its a javascript or css file by
the file name - If you have an irregular filename (i.e. a google maps api
script url) you can force it by using either of the following tags:

<!-- HEAD_include_js [my javascript file] --> <!-- HEAD_include_css [my css file] -->

Or you can write inline code to get rendered in the head:

<!-- HEAD_render <script> someJavascriptCall(); </script> -->

Todo: make it compress the js into one file... 
"""
DEFAULT_JS_TAG = '<script type="text/javascript" src="%s"></script>'
DEFAULT_CSS_TAG = '<link rel="stylesheet" type="text/css" href="%s" />'
DEFAULT_JS_DIR = 'js'
DEFAULT_CSS_DIR = 'css'

HEAD_BASE = getattr(settings, 'HEAD_INCLUDE_BASE', settings.MEDIA_URL)
PREFIX_RE = getattr(settings, 'HEAD_INCLUDE_PREFIX_RE', '<!-- *HEAD_')
SUFFIX_RE = getattr(settings, 'HEAD_INCLUDE_SUFFIX_RE', ' *-->')
TAGS = {'js': getattr(settings, 'HEAD_INCLUDE_JS_TAG', DEFAULT_JS_TAG),
        'css': getattr(settings, 'HEAD_INCLUDE_CSS_TAG', DEFAULT_CSS_TAG)}
PATHS = {'js':'/js/', 'css':'/css/'}

HEAD_RE = re.compile(
    r'%s(include|version|include_js|include_css|render) +([\s\S]*?)%s' % (PREFIX_RE, SUFFIX_RE))
HEAD_INIT_RE = re.compile(
    '%sinit%s' % (PREFIX_RE, SUFFIX_RE))

class HeadLoader:

    def __init__(self):
        self._components = []
        self._js_components = []
        self._css_components = []

    def add_component(self, new_component_name, component_type = ''):
        if component_type == 'js' and not new_component_name in self._js_components:
            self._js_components.append(new_component_name)
        elif component_type == 'css' and not new_component_name in self._css_components:
            self._css_components.append(new_component_name)
        elif component_type == '' and not new_component_name in self._components:
            self._components.append(new_component_name)

    def render(self):
        #self._components.reverse()
        head = ''
        head += '\n' + '\n'.join(self._render_component(component, 'css') for component in self._css_components)
        head += '\n' + '\n'.join(self._render_component(component, 'js') for component in self._js_components)
        head += '\n' + '\n'.join(self._render_component(component) for component in self._components)
        
        return head
        

    def _has_component(self, component_name):
        return component_name in self._components

    def _render_component(self, component_name, component_type = ''):
        
        if component_type == '':
            # check what sort of component this is - based on the file name either ending with .js or .css
            last_three = component_name[-3:]
            if last_three == '.js':
                component_type = 'js'
            elif last_three == 'css':
                component_type = 'css'
            else:
                # we don't know what to do with anything else!
                return '<!-- HEAD - unknown compoent type : %s -->' % component_name
            
        # check if we've got an absolute or external js or css file
        if component_name[:7] == 'http://' or component_name[:1] == '/': 
            return TAGS[component_type] % (component_name,)
        else:
            return TAGS[component_type] % (HEAD_BASE + PATHS[component_type] + component_name,)


class HeadIncludeMiddleware(object):
    def process_response(self, request, response):
        components = []
        js_components = []
        css_components = []
        extra_head = []
        node = HeadLoader()
        def collect(match):
            cmd, data = match.groups()
            if cmd == 'include':
                components.extend(data.split())
            elif cmd == 'include_js':
                js_components.extend(data.split())
            elif cmd == 'include_css':
                css_components.extend(data.split())
            elif cmd == 'render':
                extra_head.append(data)
            else:
                return '<!-- UNKNOWN COMMAND HEAD_%s -->' % cmd
            return ''
        
        content = HEAD_RE.sub(collect, response.content)
        
        for component in components:
            node.add_component(component)
        
        for component in js_components:
            node.add_component(component, 'js')
            
        for component in css_components:
            node.add_component(component, 'css')
    
            
        rendered = node.render() + '\n'.join(extra_head)
        content = HEAD_INIT_RE.sub(rendered, content, 1)
        response.content = HEAD_INIT_RE.sub(
            '<!-- WARNING: MULTIPLE HEAD_init STATEMENTS -->', content)
            
        return response
        

